<template>
  <!-- 新建可视化窗口配置栏 -->
  <div class="control-setter">
    <div v-if="loadingCount > 0" class="mask">
      <a-spin class="spinner" />
    </div>
    <Hform
      v-if="active"
      :items="formItems"
      :form-data="formData"
      :chart-type="chartType"
      :config-type="'dataView'"
      @change="onChange"
    ></Hform>
  </div>
</template>

<script lang="ts">
import { cloneDeep, isString, isArray, isNumber } from 'lodash'
import Hform from '@/components/form/h-form.vue'
import { getWidgetData } from '@/api/widget'
// import { queryDatalist } from '@/api/studio'
import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
import PanelSetter from '@/components/controlSetter/PanelSetter.vue'
import {
  getSettingConfig,
  getWidgetJson,
  getDefaultFormData,
} from '@/config/setting-chart'
import {
  KeyValueStore,
  GridItemDataInterface,
} from '@/components/vueGridLayout/interfate/grid-Item-data-inteface'
import { bindChartData, GeoMapGlyphChangedCallback } from '@/util/common'
import DataViewStore from '@/store/modules/dataview'
// import { infoData, nodeDataPreview } from '@/api/right-drawer'
import { viewData } from '@/api/recommend-visualization'
import { getTableData, removeNullEntries } from '@/util/recommend-visualization'
import { GeoMapEnableGlyphTypes } from '@/config/contant'

@Component({
  components: {
    Hform,
    PanelSetter,
  },
})
export default class WindowSideBar extends Vue {
  // 控制加载状态
  loadingCount: number = 0

  active: boolean = false

  /**
   * 列信息
   */
  public columnsOptions: Array<any> = []

  /**
   * 配置项
   */
  public formItems: Array<KeyValueStore> = []

  /**
   * 绑定数据
   */

  // 初始化数据
  formData: KeyValueStore = {}

  currentGridItem: any = {
    formData: {
      aggregateType: '',
      colors: [
        '#7B88F2',
        '#FBC94B',
        '#65DCB8',
        '#EF7D52',
        '#F596C6',
        '#687B9D',
        '#5EC6D7',
        '#FFA65E',
        '#CC69D9',
        '#46A9A8',
        // '#BDE8FF', '#369aff', '#73A0FA', '#5789F2', '#3874DB', '#005BBF', '#0044A4', '#122C6A'
      ],
      dataId: this.selectNode.data && this.selectNode.data.dataset_id,
      axisCategoricalDataSelection: 'xAxis',
      groupBy: '',
      labelKey: '',
      legendIsShow: false,
      title: '',
      titleIsShow: true,
      tooltipIsShow: true,
      topK: 100,
      valueKey: '',
      // xAxisGridIsShow: false,
      xAxisIsShow: true,
      xAxisPosition: 'bottom',
      // yAxisGridIsShow: false,
      yAxisIsShow: true,
      yAxisPosition: 'left',
    },
    chartType: ['barChart', 'barChart'],
    chartOptions: {
      colors: [
        '#7B88F2',
        '#FBC94B',
        '#65DCB8',
        '#EF7D52',
        '#F596C6',
        '#687B9D',
        '#5EC6D7',
        '#FFA65E',
        '#CC69D9',
        '#46A9A8',
        // '#BDE8FF', '#369aff', '#73A0FA', '#5789F2', '#3874DB', '#005BBF', '#0044A4', '#122C6A'
      ],
      groupBy: '',
      labelKey: '',
      legendIsShow: false,
      showChart: false,
      size: [550, 400],
      title: '',
      titleIsShow: true,
      tooltipIsShow: true,
      topK: 100,
      value: [],
      valueKey: '',
      // xAxisGridIsShow: false,
      xAxisIsShow: true,
      xAxisPosition: 'bottom',
      // yAxisGridIsShow: false,
      yAxisIsShow: true,
      yAxisPosition: 'left',
    },
    widgetJson: {},
    h: 5,
    i: 'id1598425567347',
    moved: false,
    resizable: true,
    w: 8,
    x: 2,
    y: 2,
  }
  chartInstanceMaps: any = {}

  public async created(): Promise<void> {
    this.initSetting()
  }

  @Prop({
    type: String,
    default: '',
  })
  chartType!: string

  @Watch('chartType', { immediate: true })
  changeChartType() {
    this.currentGridItem.chartType = [this.chartType, this.chartType]
    this.formItems = getSettingConfig(this.currentGridItem.chartType)
    this.formItems = this.formItems.filter((item) => item.name !== 'dataId')

    const index = this.formItems.findIndex(
      (item) => item.name === 'labelKeyFormat'
    )
    const field = this.fields.find(
      (item) => item.value === this.formData.labelKey
    )
    if (index >= 0 && field && field.isDate) {
      this.formItems[index].isHide = false
    } else if (index >= 0) {
      this.formItems[index].isHide = true
      this.formData.labelKeyFormat = ''
    }

    const indexShowNumberr = this.formItems.findIndex(
      (item) => item.name === 'showNumber'
    )
    if (indexShowNumberr >= 0) {
      this.formItems[indexShowNumberr].isHide = ![
        'pieChart',
        'donutChart',
      ].includes(this.chartType)
    }

    GeoMapGlyphChangedCallback(this.formData.glyph, this.formItems)
    this.setHFormItemOptions()
  }

  @Watch('currentGridItem')
  getCurrentGridItemId(newValue: GridItemDataInterface): void {
    if (newValue) {
      // this.initSetting()
    }
  }

  // Hform中select绑定options
  public setHFormItemOptions() {
    const fields = this.fields || []
    this.formItems.forEach((dataItem: KeyValueStore, index: number) => {
      if (dataItem.optionsSourse === 'columns') {
        this.$set(
          this.formItems[index].props,
          'options',
          fields.filter((column: KeyValueStore) => {
            return dataItem.optionFilter(column)
          })
        )
      }
    })
  }

  public get oldItems() {
    return DataViewStore.getOldItems
  }

  public get selectNode(): any {
    return DataViewStore.selectNode ? DataViewStore.selectNode : { data: {} }
  }

  public get projectId() {
    return (this.$route.params as any).id
  }
  private projectData: Array<any> = []

  initSetting() {
    if (this.currentGridItem) {
      this.formItems = getSettingConfig(this.currentGridItem.chartType)
      this.formItems = this.formItems.filter((item) => item.name !== 'dataId') // 排除数据集选项

      const indexShowNumberr = this.formItems.findIndex(
        (item) => item.name === 'showNumber'
      )
      if (indexShowNumberr >= 0) {
        this.formItems[indexShowNumberr].isHide = ![
          'pieChart',
          'donutChart',
        ].includes(this.chartType)
      }
    }
    this.initFormData()
    this.active = true
    // this.loadingCount += 1
    //   queryDatalist({data:{
    //     projectId: this.projectId
    //   }}).then(response => {
    //     this.loadingCount -= 1
    //    if(response.data.code === 100){
    //      this.projectData = response.data.result
    //      this.initFormData()
    //      this.setDataOption()
    //      this.active = true
    //    }
    //  }).catch(()=>{
    //     this.loadingCount -= 1
    //  })
  }

  /**
   * 初始化数据
   */
  initFormData() {
    if (this.currentGridItem && this.currentGridItem.formData) {
      const formData: KeyValueStore =
        (this.currentGridItem.formData as KeyValueStore) || {}
      if (!this.oldItems) {
        this.queryDataInfo()
      }
      Object.keys(this.currentGridItem.formData).forEach((key) => {
        if (key === 'valueKey' && formData[key] === '') {
          this.$set(this.formData, key, [
            { value: '', sort: 'asc', func: 'sum' },
          ])
        } else {
          this.$set(this.formData, key, formData[key])
        }
      })
      // 如果是重编辑可视化，需要记录配置选项，同时获取一次数据，这样可以在弹出窗口时就把之前的chart渲染出来
      if (this.oldItems) {
        this.formData = {
          ...this.formData,
          aggregateType: '',
          dataId: -1,
          ...this.oldItems.config,
          valueKey: this.oldItems.formData.valueKey,
        }
        this.currentGridItem.formData.title = this.oldItems.config.title
        //  this.currentGridItem.chartOptions.title = this.oldItems.config.title
        this.currentGridItem.formData = {
          ...this.currentGridItem.formData,
          ...this.formData,
        }
        this.currentGridItem.chartOptions = {
          ...this.currentGridItem.chartOptions,
          ...this.formData,
          size: [550, 400],
        }
        this.currentGridItem.chartType = [
          this.oldItems.chartType,
          this.oldItems.chartType,
        ]
        this.queryDataInfo()
        this.getWidgetData(this.formData)
        DataViewStore.setOldItems(null)
      }
    }
    GeoMapGlyphChangedCallback(this.formData.glyph, this.formItems)
  }
  setDataOption(): void {
    const options: Array<any> = []
    this.projectData.forEach((dataItem: any) => {
      options.push({
        ...dataItem,
        text: dataItem.name,
        value: dataItem.id,
      })
    })

    this.setOptionByName('dataId', options)
  }

  /**
   * 设置option
   */
  setOptionByName(name: string, options: Array<any>) {
    this.formItems.forEach((item, index) => {
      if (item.name === 'dataId') {
        this.$set(this.formItems[index].props, 'options', options)
      }
    })
  }

  getDefaultValueByKey(): KeyValueStore {
    if (this.currentGridItem) {
      const formData = getDefaultFormData(this.currentGridItem.chartType)
      return formData
    }
    return {}
  }
  get usedVlaueKeys(): Array<string> {
    /* eslint-disable */
    const result: Array<string> = isArray(this.formData.valueKey)
      ? this.formData.valueKey.reduce((rec, item) => {
          const rec_: Array<string> =
            item.value !== '' ? [...rec, item.value] : rec
          return rec_
        }, [])
      : this.formData.valueKey
      ? [this.formData.valueKey]
      : []
    return result
  }

  // 每次修改右侧配置信息时触发
  onChange(eventOrData: any, key: string /* , item:KeyValueStore */) {
    const value = [
      'yAxisTickIsShow',
      'xAxisTickIsShow',
      'yAxisGridIsShow',
      'xAxisGridIsShow',
    ].includes(key)
      ? eventOrData
      : this.formData[key]
    console.log('WindowSideBar.vue', key, value, eventOrData)
    const formDataDefault: KeyValueStore = this.getDefaultValueByKey()
    switch (key) {
      case 'dataId':
        this.$set(this.formData, 'labelKey', formDataDefault.labelKey || '')
        this.$set(this.formData, 'valueKey', formDataDefault.valueKey || '')
        this.$set(this.formData, 'groupBy', formDataDefault.groupBy || '')
        this.$set(this.formData, 'topK', 100)
        this.queryDataInfo()
        break
      case 'labelKey':
        if (
          value &&
          [...this.usedVlaueKeys, this.formData.groupBy].includes(value)
        ) {
          this.$message.error('维度、度量、分组字段必须互斥')
          this.$set(this.formData, 'labelKey', formDataDefault.labelKey || '')
          const index = this.formItems.findIndex(
            (item) => item.name === 'labelKeyFormat'
          )
          if (index >= 0) {
            this.formItems[index].isHide = true
            this.formData.labelKeyFormat = ''
          }
        } else {
          const index = this.formItems.findIndex(
            (item) => item.name === 'labelKeyFormat'
          )
          const field = this.fields.find(
            (item) => item.value === this.formData.labelKey
          )
          if (index >= 0 && field && field.isDate) {
            this.formItems[index].isHide = false
          } else if (index >= 0) {
            this.formItems[index].isHide = true
            this.formData.labelKeyFormat = ''
          }
        }
        break

      case 'valueKey':
        this.usedVlaueKeys.forEach((key, index) => {
          if (
            value &&
            [this.formData.labelKey, this.formData.groupBy].includes(
              this.usedVlaueKeys[index]
            )
          ) {
            this.$message.error('维度、度量、分组字段必须互斥')
            if (isString(this.formData.valueKey)) {
              this.$set(
                this.formData,
                'valueKey',
                formDataDefault.valueKey || ''
              )
            } else {
              this.$set(this.formData.valueKey[index], 'value', '')
            }
          }
        })
        /**
         * sort 互斥
         */
        if (
          isArray(this.formData.valueKey) &&
          this.formData.valueKey.length > 0
        ) {
          const find = this.formData.valueKey.find((valueKeyItem) => {
            return valueKeyItem.sort !== '' ? 1 : -1
          })
          if (find) {
            this.$set(this.formData, 'labelSortY', '')
            this.$set(this.formData, 'labelSort', '')
          }
        }
        break
      case 'groupBy':
        if (
          value &&
          [this.formData.valueKey, this.formData.labelKey].includes(value)
        ) {
          this.$message.error('维度、度量、分组字段必须互斥')
          this.$set(this.formData, 'groupBy', formDataDefault.groupBy || '')
        }
        break
      case 'topK':
        if (!isNumber(value) || value < 1) {
          this.currentGridItem.formData[key] = 1
          this.currentGridItem.chartOptions[key] = 1
          this.formData[key] = 1
        } else if (value > 9999) {
          this.currentGridItem.formData[key] = 9999
          this.currentGridItem.chartOptions[key] = 9999
          this.formData[key] = 9999
        } else {
          this.formData[key] = value
        }
        break
      case 'labelSortY':
        this.$set(this.formData, 'labelSort', '')
        if (
          isArray(this.formData.valueKey) &&
          this.formData.valueKey.length > 0
        ) {
          this.formData.valueKey.forEach((valueItem, m) => {
            this.$set(this.formData.valueKey[m], 'sort', '')
          })
        }
        break
      case 'labelSort':
        this.$set(this.formData, 'labelSortY', '')
        if (
          isArray(this.formData.valueKey) &&
          this.formData.valueKey.length > 0
        ) {
          this.formData.valueKey.forEach((valueItem, m) => {
            this.$set(this.formData.valueKey[m], 'sort', '')
          })
        }
        break

      default:
        this.currentGridItem.formData[key] = value
        this.currentGridItem.chartOptions[key] = value
        this.formData[key] = value
        console.log(
          'windowDideBar.vue onchange chartOptions',
          this.currentGridItem.chartOptions
        )
        break
    }
    this.onSettingChange()
    if (this.currentGridItem) {
      this.currentGridItem.formData[key] = value
    }
  }

  gridItemBindData(data: KeyValueStore, gridItemSet?: GridItemDataInterface) {
    const gridItem = bindChartData(gridItemSet || this.currentGridItem, data)
    if (gridItem && gridItem.chartOptions) {
      // TODO: temp: remove null entries to avoid rendering error
      gridItem.chartOptions.value = removeNullEntries(
        gridItem.chartOptions.value
      )
    }
    if (gridItem && gridItem.chartOptions) {
      const dom = (document as any).body.querySelector(
        `#grid-item-${gridItem.i}`
      )
      if (dom) {
        gridItem.chartOptions.size = [dom.offsetWidth, dom.offsetHeight]
      }
    }
    this.currentGridItem = gridItem
  }

  onSettingChange(/* newValue:{} */) {
    // @ts-ignore
    if (
      (this.formData.labelKey && this.usedVlaueKeys.length > 0) ||
      // @ts-ignore
      GeoMapEnableGlyphTypes[
        this.formData.glyph
      ] /* && this.formData.aggregateType */
    ) {
      this.getWidgetData(this.formData)
    }
  }

  // 重新获取数据
  getWidgetData(dataSetting: KeyValueStore) {
    this.loadingCount += 1
    const query: any = {
      data: {
        id: dataSetting.dataId || this.selectNode.id,
        type: dataSetting.dataType || 'task',
        widgetJson: getWidgetJson(dataSetting),
      },
    }
    this.currentGridItem.widgetJson = query
    this.currentGridItem.chartOptions = {
      ...this.currentGridItem.chartOptions,
      ...this.formData,
      size: [550, 400],
    }
    if (this.currentGridItem.chartOptions.geoTransform) {
      // 需要映射地理数据（省份、城市、ip等映射成经纬度）
      query.data.convert = this.currentGridItem.chartOptions.geoTransform.fields
    }
    console.log(
      'windowDideBar.vue getwidgetdata',
      this.currentGridItem.chartOptions
    )
    getWidgetData(query)
      .then((response) => {
        this.loadingCount -= 1
        if (response.data.code === 100) {
          this.gridItemBindData({
            query,
            data: response.data.result,
            columns: this.fields,
            formData: cloneDeep(this.formData),
          })
          // 将当前配置信息传给父组件，以重新渲染chart
          console.log('windowSideBar.vue emit', this.currentGridItem)
          this.$emit('change', this.currentGridItem)
        }
      })
      .catch(() => {
        this.loadingCount -= 1
      })
  }
  public fields: Array<any> = []
  // 获取数据信息
  async queryDataInfo() {
    this.loadingCount += 1
    const data = this.formData
    // if(this.selectNode){
    let result: any = {}
    if (this.formData.dataType === 'recommend') {
      const postData = {
        tableNames: this.formData.tableName,
      }
      const response = await viewData({ data: postData })
      result = response.data.result[0]
    } else {
      result = await getTableData(
        this.formData.tableName,
        this.formData.taskId,
        1
      )
      if (result) {
        result.head = (result?.head || []).map((h: any) => ({
          ...h,
          type: h.desc,
        }))
      } else {
        result = {}
      }
    }
    //  else if (this.formData.dataType === 'tclean') {
    //   result = await getTableData(this.formData.tableName, this.selectNode.id, 10)
    //   result.head = result.head.map((h: any) => ({...h, type: h.desc}))
    // }
    // else if(this.selectNode.type === 3) {
    //   const postData = {
    //     datasetId: this.selectNode.data.dataset_id,
    //     projectId: this.selectNode.projectId
    //   }
    //   const response = await infoData({data: postData})
    //   result = response.data.result
    // } else{
    //   const postData = {
    //     id: this.selectNode.id,
    //     pipelineId: this.selectNode.pipelineId
    //   }
    //   const response = await nodeDataPreview({data: postData})
    //   result = response.data.result[0]
    // }

    this.loadingCount -= 1
    const fields: any = []
    if (result.head && Array.isArray(result.head) && result.head.length > 0) {
      result.head.forEach((head: KeyValueStore) => {
        if (head.name === '_record_id_') return
        fields.push({
          tableId: data.dataId,
          text: head.name,
          value: head.name,
          isDate: 'date' === head.type,
          isNumber: [
            'smallint',
            'integer',
            'bigint',
            'numberic',
            'real',
            'double precision',
            'serial',
            'bigserial',
            'decimal',
            'int',
            '',
          ].includes(head.type),
        })
      })
    }
    this.formItems.forEach((dataItem: KeyValueStore, index: number) => {
      if (dataItem.optionsSourse === 'columns') {
        this.$set(
          this.formItems[index].props,
          'options',
          fields.filter((column: KeyValueStore) => {
            return dataItem.optionFilter(column)
          })
        )
      }
    })
    this.fields = fields

    const index = this.formItems.findIndex(
      (item) => item.name === 'labelKeyFormat'
    )
    const field = this.fields.find(
      (item) => item.value === this.formData.labelKey
    )
    if (index >= 0 && field && field.isDate) {
      this.formItems[index].isHide = false
    } else if (index >= 0) {
      this.formItems[index].isHide = true
      this.formData.labelKeyFormat = ''
    }

    // }
  }

  updateFormTitle(title: string) {
    this.formData.title = title
    this.currentGridItem.chartOptions.title = title
    this.currentGridItem.formData.title = title
  }
}
</script>

<style lang="less" scope>
.control-setter {
  height: 100%;
  padding-right: 8px;
  width: 100%;

  .mask {
    background: rgba(0, 0, 0, 0.05);
    height: 100%;
    position: absolute;
    text-align: center;
    width: 100%;
    z-index: 100;

    .spinner {
      left: 50%;
      position: absolute;
      top: 50%;
      transform: translate(-50%, -50%);
    }
  }

  .color-input {
    width: 170px;
  }

  // .ant-row.ant-form-item .h-input-number,
  // .ant-select {
  //   width: 170px;
  // }
}
</style>
